class Djset{
public:
    vector<int> parent,rank;
    int num;
    Djset(int n):parent(n),num(0),rank(n){
        for(int i = 0;i < n;i++){
            parent[i] = i;
        }
    }
    int find(int u){
        return u == parent[u] ? u : find(parent[u]);
    }
    bool isSet(int i,int j){
        int x = find(i);
        int y = find(j);
        if(x == y) return false;
        if(rank[x] < rank[y]){
            swap(x,y);
        }
        rank[x] += rank[y];
        parent[y] = x;
        num++;
        return true;
    }
};

class Solution {
public:
    struct edge{
        int start;
        int end;
        int len;
    };
    int minCostConnectPoints(vector<vector<int>>& points) {
        int ret = 0;
        int n = points.size();
        vector<edge> edges;
        
        Djset dj(n);
        
        for(int i = 0;i < n;i++){
            for(int j = i + 1;j < n;j++){
                int lens = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]);
                edges.push_back({i,j,lens});
            }
        }
        
        sort(edges.begin(),edges.end(),[](const auto& a,const auto& b){
            return a.len < b.len;
        });
        
        for(auto& e : edges){
            if(dj.isSet(e.start,e.end)){
                ret += e.len;
            }
            if(n == dj.num){
                break;
            }
        }
        return ret;
    }
};
